Skip to content

Make expand_defs linear in the size of the context - #303

Merged
lemmy merged 3 commits into
tlaplus:mainfrom
lemmy:expand-defs-single-pass
Nov 10, 2026
Merged

lemmy merged 3 commits into
tlaplus:mainfrom
lemmy:expand-defs-single-pass

Conversation

@lemmy

@lemmy lemmy commented Oct 12, 2026 •

Copy link
Copy Markdown
Member

Fixes #299. Part of #286.

Backend.Prep.expand_defs substituted each expanded definition into the whole remaining sequent separately: O(#expanded-defs × sequent size), quadratic on INSTANCE-heavy contexts. This PR accumulates the substitution in one pass and applies it to each hypothesis and the goal once. None stands for the identity, so hypotheses before the first expanded definition stay unchanged, as on main. The duplicate in Backend.Toolbox.expand_defs gets the same change.

Correctness

The single substitution is the composition of the per-definition ones. Outputs can differ only in how often app_expr beta-normalizes copies of inlined bodies, so they are identical when bodies are in normal form and otherwise equal up to beta-reduction.

expand_defs is pure: immutable data and persistent deques, no mutation of its input or of global state (apart from Errors.set right before failwith on arity mismatch). Comparing main's and this PR's outputs on the same input is therefore a complete check: equal outputs mean everything downstream, provers included, sees the same input. Fingerprints are computed before expand_defs and are unaffected.

Testing

main's and this PR's expand_defs ran on every obligation tlapm prepared (--noproving --nofp, no timeout), compared by strict structural equality of the whole obligation (names, visibility, Parens, locations, ...). A deliberately broken variant served as a control.

Corpus Obligations Mismatches Control detected
tlapm tests/examples/library, tlaplus/Examples, tlaps-examples, TLAPS-Bench source/, flash-proof, CCF (516 modules) 66,908 0 99.8%
specula-org/tlaps-bench-private results/ (6,787 modules) 687,757 0 99.98%

Contexts reached 2,031 hypotheses and 939 expanded definitions. A randomized test (1.2M sequents) of this PR's Prep.expand_defs and Toolbox.expand_defs gave byte-identical results for normal-form bodies and differences only up to beta-normalization for injected redexes.

dune runtest src and test/fast (48/48) pass.

Performance

expand_defs time over the corpora above: 352,682 s on main vs. 5,368 s (66×). On the CCF Raft LogInv proof, backend preparation is 7.7× faster (see #286).

@lemmy
lemmy force-pushed the expand-defs-single-pass branch from 5afd17d to 1be05cf Compare October 12, 2026 19:01
@lemmy lemmy changed the title Make expand_defs linear in the number of expanded definitions Make expand_defs linear in the size of the context Oct 12, 2026
@lemmy lemmy added the enhancement A new feature, an improvement, or other addition. label Oct 12, 2026
lemmy and others added 2 commits October 13, 2026 11:14
Signed-off-by: Markus Alexander Kuppe <github.com@lemmster.de>
Pin substitution chains, de Bruijn index shifts, binder handling,
definition visibility and selection, pragma expansion, and preservation
of untouched hypotheses, definition bodies, and obligation metadata.

Include an allocation-scaling regression test, disabled until the
repeated traversal of the context is removed.

Part of Github issue tlaplus#299
tlaplus#299

[Tests]

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Markus Alexander Kuppe <github.com@lemmster.de>
@lemmy
lemmy force-pushed the expand-defs-single-pass branch from 1be05cf to 356d9e3 Compare October 14, 2026 01:35
@lemmy
lemmy marked this pull request as ready for review October 14, 2026 01:42
@lemmy

lemmy commented Oct 14, 2026

Copy link
Copy Markdown
Member Author

/cc @Calvin-L @letFunny @qdelamea-aneo - The more reviewers, the better! :-)

@letFunny

Copy link
Copy Markdown

Hey Markus, thank you for the work here. As for my review, I am afraid I don't have enough knowledge about tlapm internals to say confidently whether this is a safe change or not. At best I would be regurgitating some AI review. However, I am happy to test the changes and report the speed up in my specs.

@lemmy

lemmy commented Nov 10, 2026

Copy link
Copy Markdown
Member Author

@kape1395 Does your verbal approval count as formal approval as well? :-)

Comment thread src/backend/prep.ml Resolved
Backend.Prep.expand_defs substituted each expanded definition into the
whole remaining sequent separately, which is quadratic in the size of
the context. Instead, accumulate the substitution in a single pass and
apply it to each hypothesis and the goal once.

Use None for the identity substitution, so that hypotheses before the
first expanded definition are left unchanged, as before.

Apply the same change to the copy in Backend.Toolbox.expand_defs.

Enable the allocation-scaling regression test. Doubling the context
must allocate less than three times as much; the old traversal
allocates approximately four times as much.

Addresses Github issue tlaplus#299
tlaplus#299

[Refactor]

Co-authored-by: qdelamea <qdelamea@aneo.fr>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Markus Alexander Kuppe <github.com@lemmster.de>
@lemmy
lemmy force-pushed the expand-defs-single-pass branch from 356d9e3 to 369884f Compare November 10, 2026 19:07
@lemmy
lemmy merged commit c579183 into tlaplus:main Nov 10, 2026
5 checks passed
@lemmy
lemmy deleted the expand-defs-single-pass branch November 10, 2026 23:04
@marco6

marco6 commented Nov 13, 2026

Copy link
Copy Markdown

A feedback from this PR: on my laptop on a rather big proof (~10K LOC in multiple files) we got:

  • for uncached results 75 minutes down to 16.
  • for cached results from 34minutes to 2.

Thanks you for this, it is amazing! :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement A new feature, an improvement, or other addition.

Development

Successfully merging this pull request may close these issues.

Prep.expand_defs is quadratic in the size of the context

4 participants